package com.yzy.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yzy.common.Result;
import com.yzy.entity.Files;
import com.yzy.mapper.FilesMapper;
import com.yzy.service.IFilesService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;

/**
 * FilesServiceImpl
 *
 * @author 杨子宇
 * @createTime 2023-04-19
 */
@Service
public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements IFilesService {
    @Value("${files.upload.path}")
    private String fileUploadPath;

    public void upload(MultipartFile file) throws IOException {
        // 获取源文件
        String originalFilename = file.getOriginalFilename();
        // 获取文件类型
        String type = FileUtil.extName(originalFilename);
        // 获取文件大小
        long size = file.getSize();

        File uploadFile = new File(fileUploadPath + originalFilename);
        // 如果文件不存在
        if (!uploadFile.getParentFile().exists()) {
            uploadFile.getParentFile().mkdirs();
        }

        String url;
        // 将文件存储在磁盘
        file.transferTo(uploadFile);
        // 获取文件MD5的值
        String md5 = SecureUtil.md5(uploadFile);
        // 根据MD5值去数据库查询文件
        Files dbFiles = getFileByMd5(md5);
        if (dbFiles != null) {
            // 内容相同时，删除重复上传的文件
            uploadFile.delete();
        } else {
            url = "http://localhost:8888/files/" + originalFilename;

            String fileName = originalFilename.split("\\.")[0];
            // 将文件存储到数据库
            Files saveFile = new Files();
            saveFile.setName(fileName);
            saveFile.setType(type);
            saveFile.setSize(size / 1024);
            saveFile.setUrl(url);
            saveFile.setMd5(md5);
            save(saveFile);
        }

    }

    private Files getFileByMd5(String md5) {
        // 查询文件的MD5是否存在
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("md5", md5);
        List<Files> filesList = list(queryWrapper);

        return filesList.size() == 0 ? null : filesList.get(0);
    }

    public void download(String file, HttpServletResponse response) throws IOException {
        // 获取文件
        File uploadFile = new File(fileUploadPath + file);
        // 设置输出流的格式
        ServletOutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file, "UTF-8"));
        response.setContentType("application/octet-stream");

        // 读取文件字节流
        os.write(FileUtil.readBytes(uploadFile));
        os.flush();
        os.close();
    }

    public Page<Files> findPage(Integer pageNum, Integer pageSize, String name, String type) {
        Page<Files> page = new Page<>(pageNum, pageSize);
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        if (!"".equals(name)) {
            queryWrapper.or().like("name", name);
        }
        if (!"".equals(type)) {
            queryWrapper.or().like("type", type);
        }
        return page(page, queryWrapper);
    }

    public boolean deleteById(Integer id) {
        // 根据id获取文件
        Files f = getById(id);
        // 获取文件的MD5值
        String md5 = f.getMd5();

        File location = new File(fileUploadPath);

        // 获取本地所以文件
        File[] listFiles = location.listFiles();
        for (File file : listFiles) {
            // 如果是文件
            if (file.isFile()) {
                // 获取文件MD5值
                String s = SecureUtil.md5(file);
                // MD5值相等时删除本地文件
                if (s.equals(md5)) {
                    file.delete();
                }
            }
        }

        return removeById(id);
    }

    public Result deleteFiles(List<Integer> ids) {
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", ids);

        File location = new File(fileUploadPath);

        // 从数据库中获取文件
        List<Files> filesList = list(queryWrapper);
        for (Files files : filesList) {
            // 获取每个文件的MD5值
            String md5 = files.getMd5();

            // 获取本地所以文件
            File[] listFiles = location.listFiles();
            for (File file : listFiles) {
                // 如果是文件
                if (file.isFile()) {
                    // 获取文件MD5值
                    String s = SecureUtil.md5(file);
                    // MD5值相等时删除本地文件
                    if (s.equals(md5)) {
                        file.delete();
                    }
                }
            }
        }

        for (Files file : list(queryWrapper)) {
            removeById(file);
        }

        return Result.success();
    }

    public boolean upDate(Files files) {
        return updateById(files);
    }
}
